
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin  = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

const { resolve } = require('path')
const htmlPublicPath = resolve(__dirname, 'build')

/**
  缓存：
  1. babel 缓存
      cacheDirectory: true
      -- > 让第二次打包更快
  2. 文件资源缓存
      hash: 每次webpack构建时会生成一个唯一的hash值
        问题：因为js和css同时使用一个hash值
          如果重新打包，会导致所有缓存失效。(可能我却只改动一个文件)
      chunkhash: 根据chunk生成的hash值。如果打包来源同一个chunk，那么hash值就一样
        问题：js和css同时使用一个hash值
          因为css是在js中引入的，所以同属一个chunk 也就是一个hash值
      contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样。
      -- > 让代码上线运行缓存更好使用
 */


const CommonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  { // 兼容性 处理css
    loader: 'postcss-loader',
    options: {
      postcssOptions: {
        plugins: [
          ["postcss-preset-env"],
        ]
      }
    }
  }
]


/**
  正常来讲，一个文件只能被一个loader处理，
  当一个文件被多个loader处理，那么一定要指定loader执行的先后顺序

  js 先执行 eslint 后 babel
  `enforce`: 'pre'
 */


module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: htmlPublicPath,
    publicPath: './',
  },
  module: {
    rules: [
      { // js eslint
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        enforce: 'pre', // 优先执行
        options: {
          fix: true
        }
      },
      {
        // 一下loader只会匹配一个
        // 注意：不能有两个配置处理同一种类型文件
        oneOf: [
          { // css
            test: /\.css$/,
            use: [...CommonCssLoader]
          },
          { // less
            test: /\.less$/,
            use: [ ...CommonCssLoader, 'less-loader']
          },
          { // js babel
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [[
                '@babel/preset-env',
                {
                  // 按需加载
                  useBuiltIns: 'usage',
                  corejs: {
                    version: 3,
                  },
                  // 执行兼容性做到哪个版本浏览器
                  targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    safari: '10',
                    edge: '17'
                  }
                }
              ]],
              // 开启babel缓存
              // 第二次构建时，会读取之前的缓存
              cacheDirectory: true,
            }
          },
          { // 图片
            test: /\.(png|jpeg|jpg|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[name].[hash:10].[ext]',
              outputPath: 'img',
            }
          },
          { // video
            test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: 'media/[name].[hash:7].[ext]',
              outputPath: 'img',
            }
          },
          { // font
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: 'fonts/[name].[hash:7].[ext]',
              outputPath: 'img',
            }
          },
          { // html  audio/img/input/data .... // https://webpack.js.org/loaders/html-loader/#getting-started
            test: /\.html$/,
            loader: 'html-loader',
          }
        ]
      }
    ]
  },
  optimization: {
    minimize: true,
    minimizer: [ // css 压缩
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
  ]
}